/**
  ******************************************************************************
  * @file    usbd_audio_out_if.c
  * @author  MCD Application Team
  * @version V1.1.0
  * @date    19-March-2012
  * @brief   This file provides the Audio Out (palyback) interface API.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "usbd_audio_core.h"
#include "usbd_audio_out_if.h"

/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
  * @{
  */


/** @defgroup usbd_audio_out_if
  * @brief usbd out interface module
  * @{
  */

/** @defgroup usbd_audio_out_if_Private_TypesDefinitions
  * @{
  */
/**
  * @}
  */


/** @defgroup usbd_audio_out_if_Private_Defines
  * @{
  */
/**
  * @}
  */


/** @defgroup usbd_audio_out_if_Private_Macros
  * @{
  */
/**
  * @}
  */


/** @defgroup usbd_audio_out_if_Private_FunctionPrototypes
  * @{
  */
static uint8_t  Init(uint32_t  AudioFreq, uint32_t Volume, uint32_t options);
static uint8_t  DeInit(uint32_t options);
static uint8_t  AudioCmd(uint8_t *pbuf, uint32_t size, uint8_t cmd);
static uint8_t  VolumeCtl(uint8_t vol);
static uint8_t  MuteCtl(uint8_t cmd);
static uint8_t  PeriodicTC(uint8_t cmd);
static uint8_t  GetState(void);

/**
  * @}
  */

/** @defgroup usbd_audio_out_if_Private_Variables
  * @{
  */
AUDIO_FOPS_TypeDef  AUDIO_OUT_fops =
{
    Init,
    DeInit,
    AudioCmd,
    VolumeCtl,
    MuteCtl,
    PeriodicTC,
    GetState
};

static uint8_t AudioState = AUDIO_STATE_INACTIVE;

/**
  * @}
  */

/** @defgroup usbd_audio_out_if_Private_Functions
  * @{
  */

/**
  * @brief  Init
  *         Initialize and configures all required resources for audio play function.
  * @param  AudioFreq: Statrtup audio frequency.
  * @param  Volume: Startup volume to be set.
  * @param  options: specific options passed to low layer function.
  * @retval AUDIO_OK if all operations succeed, AUDIO_FAIL else.
  */
static uint8_t  Init(uint32_t AudioFreq,
                     uint32_t Volume,
                     uint32_t options)
{
    static uint32_t Initialized = 0;

    /* Check if the low layer has already been initialized */
    if(Initialized == 0)
    {
        /* Call low layer function */
        if(EVAL_AUDIO_Init(OUTPUT_DEVICE_AUTO, Volume, AudioFreq) != 0)
        {
            AudioState = AUDIO_STATE_ERROR;
            return AUDIO_FAIL;
        }

        /* Set the Initialization flag to prevent reinitializing the interface again */
        Initialized = 1;
    }

    /* Update the Audio state machine */
    AudioState = AUDIO_STATE_ACTIVE;
    return AUDIO_OK;
}

/**
  * @brief  DeInit
  *         Free all resources used by low layer and stops audio-play function.
  * @param  options: options passed to low layer function.
  * @retval AUDIO_OK if all operations succeed, AUDIO_FAIL else.
  */
static uint8_t  DeInit(uint32_t options)
{
    /* Update the Audio state machine */
    AudioState = AUDIO_STATE_INACTIVE;
    return AUDIO_OK;
}

/**
  * @brief  AudioCmd
  *         Play, Stop, Pause or Resume current file.
  * @param  pbuf: address from which file shoud be played.
  * @param  size: size of the current buffer/file.
  * @param  cmd: command to be executed, can be AUDIO_CMD_PLAY , AUDIO_CMD_PAUSE,
  *              AUDIO_CMD_RESUME or AUDIO_CMD_STOP.
  * @retval AUDIO_OK if all operations succeed, AUDIO_FAIL else.
  */
static uint8_t  AudioCmd(uint8_t *pbuf,
                         uint32_t size,
                         uint8_t cmd)
{
    /* Check the current state */
    if((AudioState == AUDIO_STATE_INACTIVE) || (AudioState == AUDIO_STATE_ERROR))
    {
        AudioState = AUDIO_STATE_ERROR;
        return AUDIO_FAIL;
    }

    switch(cmd)
    {
        /* Process the PLAY command ----------------------------*/
        case AUDIO_CMD_PLAY:

            /* If current state is Active or Stopped */
            if((AudioState == AUDIO_STATE_ACTIVE) || \
                    (AudioState == AUDIO_STATE_STOPPED) || \
                    (AudioState == AUDIO_STATE_PLAYING))
            {
                Audio_MAL_Play((uint32_t)pbuf, (size / 2));
                AudioState = AUDIO_STATE_PLAYING;
                return AUDIO_OK;
            }
            /* If current state is Paused */
            else if(AudioState == AUDIO_STATE_PAUSED)
            {
                if(EVAL_AUDIO_PauseResume(AUDIO_RESUME, (uint32_t)pbuf, (size / 2)) != 0)
                {
                    AudioState = AUDIO_STATE_ERROR;
                    return AUDIO_FAIL;
                }
                else
                {
                    AudioState = AUDIO_STATE_PLAYING;
                    return AUDIO_OK;
                }
            }
            else /* Not allowed command */
            {
                return AUDIO_FAIL;
            }

        /* Process the STOP command ----------------------------*/
        case AUDIO_CMD_STOP:
            if(AudioState != AUDIO_STATE_PLAYING)
            {
                /* Unsupported command */
                return AUDIO_FAIL;
            }
            else if(EVAL_AUDIO_Stop(CODEC_PDWN_SW) != 0)
            {
                AudioState = AUDIO_STATE_ERROR;
                return AUDIO_FAIL;
            }
            else
            {
                AudioState = AUDIO_STATE_STOPPED;
                return AUDIO_OK;
            }

        /* Process the PAUSE command ---------------------------*/
        case AUDIO_CMD_PAUSE:
            if(AudioState != AUDIO_STATE_PLAYING)
            {
                /* Unsupported command */
                return AUDIO_FAIL;
            }
            else if(EVAL_AUDIO_PauseResume(AUDIO_PAUSE, (uint32_t)pbuf, (size / 2)) != 0)
            {
                AudioState = AUDIO_STATE_ERROR;
                return AUDIO_FAIL;
            }
            else
            {
                AudioState = AUDIO_STATE_PAUSED;
                return AUDIO_OK;
            }

        /* Unsupported command ---------------------------------*/
        default:
            return AUDIO_FAIL;
    }
}

/**
  * @brief  VolumeCtl
  *         Set the volume level in %
  * @param  vol: volume level to be set in % (from 0% to 100%)
  * @retval AUDIO_OK if all operations succeed, AUDIO_FAIL else.
  */
static uint8_t  VolumeCtl(uint8_t vol)
{
    /* Call low layer volume setting function */
    if(EVAL_AUDIO_VolumeCtl(vol) != 0)
    {
        AudioState = AUDIO_STATE_ERROR;
        return AUDIO_FAIL;
    }

    return AUDIO_OK;
}

/**
  * @brief  MuteCtl
  *         Mute or Unmute the audio current output
  * @param  cmd: can be 0 to unmute, or 1 to mute.
  * @retval AUDIO_OK if all operations succeed, AUDIO_FAIL else.
  */
static uint8_t  MuteCtl(uint8_t cmd)
{
    /* Call low layer mute setting function */
    if(EVAL_AUDIO_Mute(cmd) != 0)
    {
        AudioState = AUDIO_STATE_ERROR;
        return AUDIO_FAIL;
    }

    return AUDIO_OK;
}

/**
  * @brief
  *
  * @param
  * @param
  * @retval AUDIO_OK if all operations succeed, AUDIO_FAIL else.
  */
static uint8_t  PeriodicTC(uint8_t cmd)
{
    return AUDIO_OK;
}


/**
  * @brief  GetState
  *         Return the current state of the audio machine
  * @param  None
  * @retval Current State.
  */
static uint8_t  GetState(void)
{
    return AudioState;
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
